package org.moonlight.jvm.instructions.constants.ldc;

import org.moonlight.jvm.rtda.exclusive.Frame;
import org.moonlight.jvm.rtda.exclusive.OperandStack;
import org.moonlight.jvm.rtda.share.Object;
import org.moonlight.jvm.rtda.share.heap.Class;
import org.moonlight.jvm.rtda.share.heap.symref.ClassRef;
import org.moonlight.jvm.rtda.share.methodarea.RtConstantPool;
import org.moonlight.jvm.rtda.share.methodarea.StringPool;

/**
 * Ldc指令公共类
 *
 * @author Moonlight
 * @createTime 2023/8/30 16:35
 **/
public class LdcCommon {

    static void ldc(Frame frame, int idx) {
        // 当前操作数栈
        OperandStack stack = frame.getOperandStack();
        // 当前类
        Class clazz = frame.getMethod().getClazz();
        // 当前运行时常量池
        RtConstantPool rtCp = clazz.getRtCp();
        // 常量数据 - java/lang/Object 类型
        java.lang.Object constant = rtCp.getConstant(idx);

        if (constant instanceof Integer) {
            stack.pushInt((int) constant);
        } else if (constant instanceof Float) {
            stack.pushFloat((float) constant);
        } else if (constant instanceof Long) {
            stack.pushLong((long) constant);
        } else if (constant instanceof Double) {
            stack.pushDouble((double) constant);
        } else if (constant instanceof String) {
            Object myString = StringPool.myString(clazz.getLoader(), (String) constant);
            stack.pushRef(myString);
        }else if (constant instanceof ClassRef) {
            // 和基本类型、字符串字面值一样，类对象字面值也是由ldc指令加载的
            // 类对象字面量 == 类符号引用
            ClassRef classRef = (ClassRef) constant;
            // 通过类符号引用解析出对应的类，再通过类的类对象推入操作数栈
            Object jClassObj = classRef.resolvedClass().getJClass();
            stack.pushRef(jClassObj);
        } else {
            throw new ClassFormatError();
        }
    }

}